#include "seu_external.h"
#include "seu_kernel.h"


/**
 * @brief: timer section
*/
#if (SEU_TIMER_MAX > 0)
SEU_TIMER seu_timer[SEU_TIMER_MAX];
#endif

void seu_thread_slicetime_set(seu_uint32_t ms)
{
    seu_sys.thread_slicetime = ms;
}

seu_uint32_t seu_clock_get(void)
{
    return seu_sys.sys_clock_count;
}

#if (SEU_TIMER_MAX > 0)
static void seu_timer_handler_set(seu_uint8_t id, seu_handler_t handler)
{
    seu_timer[id].timer_handler = handler;
}

static void seu_timer_reload_set(seu_uint8_t id, seu_uint32_t ticks)
{
    os_lock();
    seu_timer[id].timer_count = ticks;
    seu_timer[id].timer_reload = ticks;
    os_unlock();
}
 
// only TIMER_ONCE can use
static void seu_timer_count_set(seu_uint8_t id, seu_uint32_t ticks)
{
    os_lock();
    seu_timer[id].timer_count = ticks;
    seu_timer[id].timer_count = 0;
    seu_timer[id].statue = SEU_TRUE;
    os_unlock();
}

static seu_uint32_t seu_timer_count_get(seu_uint8_t id)
{
    return seu_timer[id].timer_count;
}

struct __SEU_TIMER_OPS timer_ops = {
    .seu_timer_handler_set = seu_timer_handler_set,
    .seu_timer_reload_set = seu_timer_reload_set,
    .seu_timer_count_set = seu_timer_count_set,
    .seu_timer_count_get = seu_timer_count_get,
};

struct __SEU_TIMER *seu_timer_init(seu_uint8_t id, struct __SEU_TIMER *config)
{
    if(id >= SEU_TIMER_MAX)
    return NULL;
    if(config->timer_flag == TIMER_FREQUENCY){
        seu_timer[id].timer_flag = TIMER_FREQUENCY;
        seu_timer[id].timer_reload = config->timer_reload;
    }else{
        seu_timer[id].timer_flag = TIMER_ONECE;
        seu_timer[id].timer_reload = 0;
    }
    seu_timer[id].timer_count = config->timer_count;
    seu_timer[id].timer_handler = config->timer_handler;
    seu_timer[id].timer_param.vect = config->timer_param.vect;
    seu_timer[id].timer_param.config = config->timer_param.config;
    seu_timer[id].timer_ops = &timer_ops;
    seu_timer[id].statue = SEU_TRUE;
    return &seu_timer[id];
}
#endif


/**
 *  flag section
*/
#if (SEU_FLAG_MAX > 0)

#if (SEU_FLAG_MAX % 8 == 0)
seu_uint8_t seu_flag[SEU_FLAG_MAX/8];
#else
seu_uint8_t seu_flag[SEU_FLAG_MAX/8+1];
#endif
// seu_uint8_t seu_flag[1] each bit represent a id, total 8 in one arry
// 0x07 only define 3
seu_rt seu_flag_pend(seu_pend_type mode, seu_uint8_t id)
{
    if(mode == SEU_UNBLOCK){
        if((seu_flag[id>>3] & (1 << (id&0x07))) == 0)
            return SEU_FALSE;
    }else{
        while((seu_flag[id>>3] & (1 << (id&0x07))) == 0)
            seu_delay(1);
    }
    // after pend, this bit will be zero
    seu_flag[id>>3] &= ~(1 << (id&0x07));
    return SEU_FALSE;
}

void seu_flag_post(seu_uint8_t id)
{
    seu_flag[id>>3] |= 1 << (id&0x07);
}
#endif

/**
 *  mutex section
*/
#if (SEU_MUTEX_MAX > 0)
seu_uint8_t seu_mutex[SEU_MUTEX_MAX];
seu_rt seu_mutex_pend(seu_pend_type mode, seu_uint8_t id)
{
    if(mode == SEU_UNBLOCK){
        if(seu_mutex[id] != 0)
            return SEU_FALSE;
    }else{
        while(seu_mutex[id] != 0)
            seu_delay(1);
    }
    seu_mutex[id] = seu_tcb_cur->prio;
    return SEU_TRUE;
}

void seu_mutex_post(seu_uint8_t id)
{
    if(seu_mutex[id] == seu_tcb_cur->prio){
        seu_mutex[id] = 0;
    }
}
#endif


/**
 *  mbox section
*/

#if (SEU_MBOX_MAX > 0)
SEU_MBOX seu_mbox[SEU_MBOX_MAX];

seu_rt seu_mbox_pend(seu_pend_type mode, seu_uint8_t id, SEU_MBOX *mbox)
{
    if(mode == SEU_UNBLOCK){
        if(seu_mbox[id].mbox_datalen == 0)
            return SEU_FALSE;
    }else{
        while(seu_mbox[id].mbox_datalen == 0)
            seu_delay(1);
    }
    *mbox = seu_mbox[id];
    seu_mbox[id].mbox_datalen = 0;
    seu_mbox[id].mbox_pdata = NULL;
    return SEU_TRUE;
}

void seu_mbox_post(seu_uint8_t id, SEU_MBOX *mbox)
{
    seu_mbox[id] = *mbox;
}
#endif

